# -*- coding: utf-8 -*-
import json, os

from xml.dom import minidom
from xml.etree import ElementTree
from openai import OpenAI

import include

class App:
    @staticmethod
    def factory(name: str = ''):
        return App(name)

    def __init__(self, name: str):
        self.name = name

        self._pid = None
        self._local_ip = None
        self._redis = None
        self._scheduler = None
        self._converter = None
    @property
    def pid(self) :
        if self._pid is None :
            self._pid = os.getpid()
        return self._pid
    @property
    def config(self) :
        return include
    @property
    def converter(self) :
        if self._converter is None :
            # from app.converter import Converter
            self._converter = Converter()
        return self._converter
    
    def load(self):
        pass
    def convert(self):
        self.converter.convert()

class Converter:
    def get_response(self, filename: str) -> dict[str, any]:
        with open(filename, "r", encoding="utf-8") as f:
            return json.load(f)
    def prettify_xml(self, element: ElementTree.Element) -> str:
        """将XML元素转换为格式化的字符串"""
        rough_string = ElementTree.tostring(element, 'utf-8')
        reparsed = minidom.parseString(rough_string)
        return reparsed.toprettyxml(indent="  ", encoding="utf-8").decode("utf-8")

    def save_to_file(self, content: str, filename: str) -> None:
        """将内容保存到文件"""
        try:
            dirname = os.path.dirname(filename)
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            with open(filename, 'w', encoding='utf-8') as f:
                f.write(content)
            print(f"文件已保存为: {filename}")
        except Exception as e:
            print(f"保存文件时出错: {e}")
    def response_to_middle(self, response: dict[str, any], middle_filename: str):
        choices = response.get("choices", [])
        if choices and isinstance(choices[0], dict):
            message = choices[0].get("message", {})
            content = message.get("content", "")
        self.save_to_file(content, middle_filename)
        with open(middle_filename, "r", encoding="utf-8") as f:
            return f.read()
    def middle_to_parts(self, middle_content: str, base_filename: str):
        parts = []
        xml_parts = middle_content.split('<?xml version="1.0" encoding="UTF-8"?>')
        part_dir = os.path.dirname(base_filename)
        # 遍历拆分后的 XML 部分
        for i, part in enumerate(xml_parts):
            # 去除前后空白字符
            part = part.strip()
            # 如果部分不为空
            if part:
                # 生成相对输出文件名
                if 'chapter' in part:
                    part_filename = f'chapters{os.sep}chapters-{i}.xml'
                else:
                    part_filename = f'sections{os.sep}sections-{i}.xml'
                # 为每个部分添加 XML 声明
                xml_content = '<?xml version="1.0" encoding="UTF-8"?>\n' + part
                # 生成输出文件名
                # output_file_name = f'{part_filename}/sections/sections-{i}.xml'
                output_filename = f'{part_dir}{os.sep}{part_filename}'
                output_dir = os.path.dirname(output_filename)
                if not os.path.exists(output_dir):
                    os.makedirs(output_dir)
                # 打开输出文件并写入内容
                with open(output_filename, 'w', encoding='utf-8') as output_file:
                    output_file.write(xml_content)
                print(f'已生成文件: {output_filename}')
                parts.append((output_filename, part_filename))
        return parts
    def create_basefile(self, parts: list[str], base_filename: str) -> None:
        content = '<?xml version="1.0" encoding="UTF-8"?>\n' \
        '<!DOCTYPE book\n' \
        '[\n' \
            '  <!ENTITY chunxinmail  "chunxin@doc.press">\n' \
        ']>\n' \
        '<book xmlns="http://docbook.org/ns/docbook" xmlns:xlink=\'http://www.w3.org/1999/xlink\' xmlns:xi="http://www.w3.org/2001/XInclude" xml:lang="zh_cn" xml:id="CreateABook" version="5.0">\n'
        for part in parts:
            content += f'  <xi:include href="{part}" xmlns:xi="http://www.w3.org/2001/XInclude"/>\n'
        content += '</book>'
        with open(base_filename, "w", encoding="utf-8") as f:
            f.write(content)
        return content

    def remove_file(self, filename: str) -> None:
        try:
            os.remove(filename)
            print(f"文件已删除: {filename}")
        except Exception as e:
            print(f"删除文件时出错: {e}")
    def openai(self, subject: str):
        client = OpenAI(api_key=app.config.DEEPSEEK_KEY, base_url="https://api.deepseek.com")
        completion = client.chat.completions.create(
            model="deepseek-chat",
            # model="deepseek-reasoner",
            messages=[
                # {"role": "system", "content": "You are a helpful assistant"},
                # "苏州吃喝玩乐"
                {"role": "user", "content": f"请生成一篇关于主题“{subject}”的文章,生成docbook5格式内容,分多个章节,每个章节单独一个docbook文件,只输出dockbook内容,不含(```xml)等"},
            ],
            stream=False
        )
        response_filename = app.config.RESPONSE_FILE
        response = completion.model_dump_json(indent=2)
        self.save_to_file(response, response_filename)
        print(f"响应已保存到:{response_filename}")
        return response
    def convert(self) -> None:
        subject = app.config.SUBJECT
        if subject and subject != "":
            if not app.config.DEEPSEEK_KEY or app.config.DEEPSEEK_KEY == "":
                print("没有配置DeepSeek Key")
                return
            response = self.openai(app.config.SUBJECT)
            response = json.loads(response)
        elif app.config.RESPONSE_FILE and os.path.exists(app.config.RESPONSE_FILE):
            response = self.get_response(app.config.RESPONSE_FILE)
        else:
            print("没有主题或响应文件")
            return
        middle = self.response_to_middle(response, app.config.MIDDLE_FILE)
        parts = self.middle_to_parts(middle, app.config.DOCPRESS_FILE)
        content = self.create_basefile([part for _, part in parts], app.config.DOCPRESS_FILE)

        self.remove_file(app.config.MIDDLE_FILE)

        print(f"转换完成，内容已写入到 {app.config.DOCPRESS_FILE}")

app = App.factory(include.APP_NAME)

if __name__ == '__main__':
    app.load()
    app.convert()